package com.scau.clothes.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.scau.clothes.dao.OrderDao;
import com.scau.clothes.pojo.Clothes;
import com.scau.clothes.pojo.Order;
import com.scau.clothes.pojo.OrderClothes;
import com.scau.clothes.pojo.User;
import com.scau.clothes.pojo.enumclass.OrderStatus;
import com.scau.clothes.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    MailService mailService;
    @Autowired
    OrderDao orderDao;
    @Autowired
    UserService userService;
    @Autowired
    PayService payService;
    @Autowired
    CartService cartService;
    @Autowired
    ClothesService clothesService;
    @Autowired
    ClothesStockService clothesStockService;
    @Autowired
    RabbitTemplate rabbitTemplate;
    private static String ORDER = "ORDER";
    private static String CART = "CART";
    @Override
    public Order createOrderByUserId(int userId) {
        List<OrderClothes> ocList = cartService.getOCByUserIdInRedis(userId);
        Order order = new Order();
        order.setUserId(userId);
        order.setOrderStatus(OrderStatus.NOT_PAY);
        BigDecimal tp = new BigDecimal(0);
        BigDecimal ap = new BigDecimal(0);

        for (OrderClothes oc : ocList) {

            tp = tp.add(oc.getTotalPrice());
            ap = ap.add(oc.getActualTotalPrice());
        }
        order.setTotalPrice(tp);
        order.setActualPrice(ap);
        String orderJSON = JSONObject.toJSONString(order);
        System.out.println(orderJSON);
        redisTemplate.opsForValue().set(ORDER+userId,orderJSON);
        return order;
    }

    @Override
    public Order payTheOrderByUserId(int userId, int payType) {
        log.info("开始支付");
        String orderJSON = (String) redisTemplate.opsForValue().get(ORDER + userId);

        if(orderJSON == null){
            return null;
        }

        Order order = JSONObject.parseObject(orderJSON, Order.class);
        Order res = payService.pay(userId, order, order.getActualPrice(), payType);
        if(res == null)
            return res;

        Map<String,Object> info = new HashMap<>();
        info.put("order",res);
        rabbitTemplate.convertAndSend("doAfterPayQ",info);
//        doAfterPaySuccess(info);
        log.info("支付完成");
        return res;
    }

    /**
     * 支付的后续处理 交给rabbitmq处理
     * @param info
     */
    @RabbitListener(queuesToDeclare = @Queue("doAfterPayQ"))
    private void doAfterPaySuccess(Map<String,Object> info){
        Order order = ((Order) info.get("order"));
        handleOrderDao(order.getUserId(),order);
        updateRedis(order.getUserId());
    }
    /**
     * 将order与对应oc持久化 更新排行榜 更新库存
     * @param userId
     * @param order
     */
    private void handleOrderDao(int userId,Order order){
        orderDao.insertOrder(order);
        List<OrderClothes> ocList = cartService.getOCByUserIdInRedis(userId);
        for (OrderClothes oc : ocList) {
            clothesStockService.updateStockByClothesId(oc.getClothesId(),oc.getNum());
            clothesService.updateHotSale(oc.getClothesId(),oc.getNum());
            oc.setOrderId(order.getId());
//            orderClothesDao.insertOC(oc);
        }
        //sql优化，逐条插入优化成批量插入
        cartService.insertOCList(ocList);
        //发送凭证
        sendMail(order,ocList);
    }
    /**
     * 更新redis 删除某些key
     * @param userId
     */
    private void updateRedis(int userId){
        redisTemplate.delete(ORDER+userId);
        redisTemplate.delete(CART+userId);
    }
    private void sendMail(Order order,List<OrderClothes> ocList){
        Integer userId = order.getUserId();
        String email = userService.getEmailById(userId);
        String receipt = createReceipt(order,ocList);
        String title = "胖墩儿服装店购物凭证";
        mailService.sendMail(email,title,receipt);
    }
    private String createReceipt(Order order,List<OrderClothes> ocList){
        StringBuffer buf = new StringBuffer();
        buf.append("***************购物凭证***************"+'\n');
        buf.append("订单Id:"+order.getId()+'\n');
        buf.append("支付方式:"+order.getPayType()+'\n');
        buf.append("总价格:"+order.getTotalPrice()+"元"+'\n');
        buf.append("实际价格:"+order.getActualPrice()+"元"+'\n');
        buf.append("优惠了:"+order.getTotalPrice().subtract(order.getActualPrice())+"元"+'\n');
        buf.append("***************购物清单***************"+'\n');
        int i=1;
        for (OrderClothes oc : ocList) {
            Clothes clothes = clothesService.getClothesById(oc.getClothesId());
            buf.append(i+".");
            buf.append("衣服id:"+clothes.getId()+";"+'\n');
            buf.append("衣服名称:"+clothes.getClothesName()+";"+'\n');
            buf.append("衣服大小:"+clothes.getSize()+";"+'\n');
            buf.append("衣服单价:"+clothes.getPrice()+"元"+";"+'\n');
            if(clothes.getPromotionStatus()==1)
                buf.append("衣服优惠价:"+clothes.getPromotionPrice()+"元;"+'\n');
            buf.append("购买数量:"+oc.getNum()+";"+'\n');
            buf.append("总价:"+oc.getTotalPrice()+"元;"+'\n');
            buf.append("实际总价:"+oc.getActualTotalPrice()+"元"+'\n');
            buf.append("******************************************"+'\n');
            i++;
        }
        return buf.toString();
    }

    @Override
    public int insertOrder(Order order) {
        return orderDao.insertOrder(order);
    }

    @Override
    public List<Order> getOrdersByUserId(int id) {
        return orderDao.getOrdersByUserId(id);
    }

    @Override
    public Order getOrderByOrderId(int orderId) {
        return orderDao.getOrderByOrderId(orderId);
    }

    @Override
    public User getUserByOrderId(int id) {
        return orderDao.getUserByOrderId(id);
    }

    @Override
    public void updateOrder(Order order) {
        orderDao.updateOrder(order);
    }
}
